// Copyright (c) 2021 Presto Labs Pte. Ltd.
// Author: hyuan

#include "coin2/exchange/gateio_futures/api_order/native_rest_async_asio_subscriber.h"

#include <glog/logging.h>

#include "coin2/exchange/order/gateio.pb.h"

namespace coin2::exchange::gateio_futures::api_order {

void GateioFuturesRestAsyncAsioSubscriber::QueryBalance(const std::string& currency) {
  RestParams params;
  params.set_settle(currency);
  auto http_context = rest_client()->QueryAccountBalance(params);
  if (!http_context) {
    return;
  }
  http_context->handler =
      std::bind(&GateioFuturesRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void GateioFuturesRestAsyncAsioSubscriber::QueryPosition(const std::string& currency) {
  RestParams params;
  params.set_settle(currency);
  auto http_context = rest_client()->QueryAccountPosition(params);
  if (!http_context) {
    return;
  }
  http_context->handler =
      std::bind(&GateioFuturesRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void GateioFuturesRestAsyncAsioSubscriber::QueryOpenOrders(
    const std::string& currency,
    const std::string& contract) {
  RestParams params;
  params.set_settle(currency);
  params.set_contract(contract);
  auto http_context = rest_client()->QueryOpenOrders(params);
  if (!http_context) {
    return;
  }
  http_context->handler =
      std::bind(&GateioFuturesRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void GateioFuturesRestAsyncAsioSubscriber::QueryHistOrders(
    const std::string& currency,
    const std::string& contract) {
  RestParams params;
  params.set_settle(currency);
  params.set_contract(contract);
  auto http_context = rest_client()->QueryHistOrders(params);
  if (!http_context) {
    return;
  }
  http_context->handler =
      std::bind(&GateioFuturesRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void GateioFuturesRestAsyncAsioSubscriber::QueryHistTrades(const std::string& currency) {
  RestParams params;
  params.set_settle(currency);
  auto http_context = rest_client()->QueryHistTrades(params);
  if (!http_context) {
    return;
  }
  http_context->handler =
      std::bind(&GateioFuturesRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void GateioFuturesRestAsyncAsioSubscriber::QueryTradingFee() {
  auto http_context = rest_client()->QueryTradingFee();
  if (!http_context) {
    return;
  }
  http_context->handler =
      std::bind(&GateioFuturesRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void GateioFuturesRestAsyncAsioSubscriber::SubscribeAsync() {
  AddPeriodicTask(
      std::bind(&GateioFuturesRestAsyncAsioSubscriber::QueryTradingFee, this),
      config_.query_account_balance_period_sec(),
      "query_trading_fee");

  const auto currency_list = [&, this]() -> std::unordered_set<std::string> {
    std::unordered_set<std::string> ret;
    for (const auto* currency : symcache_->GetCurrencies()) {
      std::string ccy = currency->order_currency();
      boost::to_lower(ccy);
      ret.emplace(std::move(ccy));
    }
    return ret;
  }();

  AddPeriodicTask(
      std::bind(&GateioFuturesRestAsyncAsioSubscriber::QueryBalance, this, std::placeholders::_1),
      config_.query_account_balance_period_sec(),
      "query_balance",
      currency_list);
  AddPeriodicTask(
      std::bind(&GateioFuturesRestAsyncAsioSubscriber::QueryPosition, this, std::placeholders::_1),
      config_.query_account_position_period_sec(),
      "query_position",
      currency_list);
  AddPeriodicTask(
      std::bind(
          &GateioFuturesRestAsyncAsioSubscriber::QueryHistTrades,
          this,
          std::placeholders::_1),
      config_.query_fill_period_sec(),
      "query_fills",
      currency_list);

  const auto symbol_list = native_symbols();
  AddPeriodicTask(
      std::bind(
          &GateioFuturesRestAsyncAsioSubscriber::QueryOpenOrders,
          this,
          std::placeholders::_1,
          std::placeholders::_2),
      config_.query_open_orders_period_sec(),
      "query_open_orders",
      currency_list,
      symbol_list);
  AddPeriodicTask(
      std::bind(
          &GateioFuturesRestAsyncAsioSubscriber::QueryHistOrders,
          this,
          std::placeholders::_1,
          std::placeholders::_2),
      config_.query_cancel_orders_period_sec(),
      "query_hist_orders",
      currency_list,
      symbol_list);
}

}  // namespace coin2::exchange::gateio_futures::api_order
